/*=============================================================================
# FileName    :	axi_stream_drive.svh
# Author      :	author
# Email       :	email@email.com
# Description :	
# Version     :	1.0
# LastChange  :	2018-09-17 17:00:54
# ChangeLog   :	
=============================================================================*/

`ifndef AXI_STREAM_DRIVE_H
`define AXI_STREAM_DRIVE_H

class axi_stream_drive #(int width = 32);
    virtual axi_stream_bfm #(.WIDTH (width) )    bfm;
    /*
     * 静态属性
     */
    function new(virtual axi_stream_bfm #(.WIDTH (width) ) b);  // 需要赋初值的属性
        bfm = b;
    endfunction

    // brief: 将数据data中的数据发送出去
    extern task write(int data[], int len, e_use_tready slave_ready);

    //If a slave asserts TREADY, 
    //it is permitted to deassert TREADY before TVALID is asserted.
    /**
    * @brief 产生指定时间的tready信号, 不关心tvalid信号
    *
    * @param num
    * @param interval
    */
    extern task read(int num, int interval);

endclass

task axi_stream_drive::write(int data[], int len, e_use_tready slave_ready);
    // int len = $size(data);
    @ (posedge bfm.s_aclk);
    for(int i = 0; i < len; )  // 等待tready后增加
    begin
        bfm.m_axis_tvalid = 1;
        bfm.m_axis_tdata = data[i];

        if(slave_ready == TRUE)
            wait(bfm.m_axis_tready);

        if(i == len-1)
            bfm.m_axis_tlast = 1;
        i++;
        @ (posedge bfm.s_aclk);
    end
    bfm.m_axis_tlast = 0;
    bfm.m_axis_tvalid = 0;
    bfm.m_axis_tdata = 0;
endtask


task axi_stream_drive::read(int num, int interval);
    @(posedge bfm.s_aclk);
    bfm.s_axis_tready = 1;
    repeat(num)
    begin
        @(posedge bfm.s_aclk);
        if(interval != 0)
        begin
            bfm.s_axis_tready = 0;
            repeat(interval)
                @(posedge bfm.s_aclk);
            bfm.s_axis_tready = 1;
        end
    end
    bfm.s_axis_tready = 0;
endtask
`endif
